home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / scsiDiskBoot / RCS / devSCSI.c,v < prev    next >
Encoding:
Text File  |  1989-06-10  |  54.7 KB  |  2,081 lines

  1. head     1.9;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    mendel:1.9; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.9
  10. date     89.01.06.08.13.04;  author brent;  state Exp;
  11. branches ;
  12. next     1.8;
  13.  
  14. 1.8
  15. date     88.03.31.10.10.30;  author brent;  state Exp;
  16. branches ;
  17. next     1.7;
  18.  
  19. 1.7
  20. date     87.05.12.12.45.35;  author brent;  state Exp;
  21. branches ;
  22. next     1.6;
  23.  
  24. 1.6
  25. date     87.05.11.11.11.30;  author brent;  state Exp;
  26. branches ;
  27. next     1.5;
  28.  
  29. 1.5
  30. date     87.05.08.17.42.55;  author brent;  state Exp;
  31. branches ;
  32. next     1.4;
  33.  
  34. 1.4
  35. date     86.07.24.11.26.35;  author brent;  state Exp;
  36. branches ;
  37. next     1.3;
  38.  
  39. 1.3
  40. date     86.07.21.09.32.35;  author brent;  state Exp;
  41. branches ;
  42. next     1.2;
  43.  
  44. 1.2
  45. date     86.07.18.13.06.04;  author brent;  state Exp;
  46. branches ;
  47. next     1.1;
  48.  
  49. 1.1
  50. date     86.07.16.17.32.11;  author brent;  state Exp;
  51. branches ;
  52. next     ;
  53.  
  54.  
  55. desc
  56. @Kernel version, unmodified for boot program yet.
  57. @
  58.  
  59.  
  60. 1.9
  61. log
  62. @New include files and constants due to source reorganization
  63. @
  64. text
  65. @/* 
  66.  * devSCSI.c --
  67.  *
  68.  *    SCSI = Small Computer System Interface.
  69.  *    Device driver for the SCSI disk and tape interface.
  70.  *
  71.  *    SLIMLINE VERSION FOR BOOT PROGRAM.  If this is compiled with
  72.  *    -DNO_PRINTF then that reduces the size by a third:
  73.  *    text    data    bss     dec     hex
  74.  *    2564    640     8       3212    c8c     devSCSI.o
  75.  *    1960    44    8    2012    7dc    (-DNO_PRINTF)
  76.  *
  77.  * Copyright 1986 Regents of the University of California
  78.  * All rights reserved.
  79.  */
  80.  
  81. #ifndef lint
  82. static char rcsid[] = "$Header: devSCSI.c,v 1.8 88/03/31 10:10:30 brent Exp $ SPRITE (Berkeley)";
  83. #endif not lint
  84.  
  85.  
  86. #include "sprite.h"
  87. #include "boot.h"
  88. #include "dev.h"
  89. #include "devInt.h"
  90. #include "devSCSI.h"
  91.  
  92. #include "devMultibus.h"
  93. #include "devDiskLabel.h"
  94. #include "sys.h"
  95. #include "fs.h"
  96. #include "fsDisk.h"
  97. #include "user/byte.h"
  98. #include "mach.h"
  99. #include "machMon.h"
  100.  
  101. /*
  102.  * Boot program idioms
  103.  */
  104. #define Sys_Printf Mach_MonPrintf
  105.  
  106. /*
  107.  * State for each SCSI controller.
  108.  */
  109. static DevSCSIController *scsi[SCSI_MAX_CONTROLLERS];
  110.  
  111. /*
  112.  * State for each SCSI disk.  The state for all SCSI disks are kept
  113.  * together so that the driver can easily find the disk and partition
  114.  * that correspond to a filesystem unitNumber.
  115.  */
  116.  
  117. #ifdef SCSI_DISK_BOOT
  118. DevSCSIDevice *scsiDisk[SCSI_MAX_DISKS];
  119. static int scsiDiskIndex = -1;
  120. #endif SCSI_DISK_BOOT
  121.  
  122. /*
  123.  * State for the SCSI Tape drive.  This is a back pointer to the
  124.  * SCSI specific information needed by the driver.
  125.  */
  126. #ifdef SCSI_TAPE_BOOT
  127. DevSCSIDevice *scsiTape[SCSI_MAX_TAPES];
  128. static int scsiTapeIndex = -1;
  129. #endif SCSI_TAPE_BOOT
  130.  
  131. /*
  132.  * SECTORS_PER_BLOCK
  133.  */
  134. #define SECTORS_PER_BLOCK    (FS_BLOCK_SIZE / DEV_BYTES_PER_SECTOR)
  135.  
  136. /*
  137.  * Forward declarations.
  138.  */
  139.  
  140. void        DevSCSIReset();
  141. ReturnStatus    DevSCSITest();
  142. void        DevSCSIDoLabel();
  143. void        DevSCSISetupCommand();
  144. ReturnStatus    DevSCSICommand();
  145. ReturnStatus    DevSCSIStatus();
  146. ReturnStatus    DevSCSIWait();
  147.  
  148. #ifdef SCSI_TAPE_BOOT
  149. void        DevSCSISetupTapeCommand();
  150. ReturnStatus    DevSCSITapeError();
  151. #endif SCSI_TAPE_BOOT
  152. #ifdef SCSI_DISK_BOOT
  153. ReturnStatus    DevSCSIDiskError();
  154. #endif
  155.  
  156.  
  157. /*
  158.  *----------------------------------------------------------------------
  159.  *
  160.  * Dev_SCSIInitController --
  161.  *
  162.  *    Initialize an SCSI controller.
  163.  *
  164.  * Results:
  165.  *    None.
  166.  *
  167.  * Side effects:
  168.  *    Allocate buffer space associated with the controller.
  169.  *    Do a hardware reset of the controller.
  170.  *
  171.  *----------------------------------------------------------------------
  172.  */
  173. Boolean
  174. Dev_SCSIInitController(cntrlrPtr)
  175.     register DevConfigController *cntrlrPtr;    /* Config info for controller */
  176. {
  177.     register DevSCSIController *scsiPtr;    /* SCSI specific state */
  178.     register DevSCSIRegs *regsPtr;        /* Control registers for SCSI */
  179.     register int x;            /* Used when probing the controller */
  180.  
  181.     /*
  182.      * Allocate space for SCSI specific state and
  183.      * initialize the controller itself.
  184.      */
  185.     scsiPtr = (DevSCSIController *)Mem_Alloc(sizeof(DevSCSIController));
  186.     scsi[cntrlrPtr->controllerID] = scsiPtr;
  187.     scsiPtr->number = cntrlrPtr->controllerID;
  188.  
  189.     /*
  190.      * Poke at the controller's registers to see if it works
  191.      * or we get a bus error.
  192.      */
  193.     scsiPtr->regsPtr = (DevSCSIRegs *)cntrlrPtr->address;
  194.     regsPtr = scsiPtr->regsPtr;
  195.     x = Dev_Poke(®sPtr->dmaCount, 0xBABE);
  196.     if (x == 0) {
  197.     x = Dev_Peek(®sPtr->dmaCount);
  198.     if (x != 0xBABE) {
  199. #ifndef NO_PRINTF
  200.         Sys_Printf("SCSI-%d: control register read-back problem <%x>\n",
  201.                  scsiPtr->number, x);
  202. #endif
  203.         return(FALSE);
  204.     }
  205.     } else {
  206.     /*
  207.      * Got a bus error. Zap the info about the non-existent controller.
  208.      */
  209.     scsi[cntrlrPtr->controllerID] = (DevSCSIController *)NIL;
  210.     return(FALSE);
  211.     }
  212.     regsPtr->intrVector = cntrlrPtr->vectorNumber;
  213.     DevSCSIReset(regsPtr);
  214.  
  215. #ifndef NO_PRINTF
  216.     Sys_Printf("SCSI-%d at address %x\n", scsiPtr->number, cntrlrPtr->address);
  217. #endif
  218.     /*
  219.      * Allocate the mapped multibus memory to buffers:  one small buffer
  220.      * for sense data, a one sector buffer for the label, and one buffer
  221.      * for reading and writing filesystem blocks. The use of the label and
  222.      * sense buffer relies on the monitor having multibus memory mapped int.
  223.      * The general buffer gets mapped just before a read or write.
  224.      * It has to be twice as large as
  225.      * a filesystem block so that an unaligned block can be mapped into it.
  226.      */
  227.     scsiPtr->senseBuffer = (DevSCSISense *)Dev_IOAlloc(sizeof(DevSCSISense));
  228.  
  229.     scsiPtr->labelBuffer = (Address)Dev_IOAlloc(DEV_BYTES_PER_SECTOR);
  230.  
  231.     scsiPtr->IOBuffer = (Address)Dev_IOAlloc(2 * FS_BLOCK_SIZE);
  232.     
  233.     scsiPtr->flags = SCSI_CNTRLR_ALIVE;
  234.  
  235.     return(TRUE);
  236. }
  237.  
  238. /*
  239.  *----------------------------------------------------------------------
  240.  *
  241.  * Dev_SCSIInitDevice --
  242.  *
  243.  *    Initialize a device hanging off an SCSI controller.  This may
  244.  *     include checking that the device exists.  State is set up for
  245.  *    future operations on the device, and then tape or disk specific
  246.  *    initialiazation is done.  This keeps track of how many times it
  247.  *    is called with for disks and tapes so that it can properly correlate
  248.  *    filesystem unit numbers to particular devices.
  249.  *
  250.  * Results:
  251.  *    None.
  252.  *
  253.  * Side effects:
  254.  *    Disks:  The label sector is read and the partitioning of
  255.  *    the disk is set up.  The partitions correspond to device
  256.  *    files of the same type but with different unit number.
  257.  *
  258.  *----------------------------------------------------------------------
  259.  */
  260. Boolean
  261. Dev_SCSIInitDevice(devConfPtr)
  262.     register DevConfigDevice *devConfPtr;   /* Config info about the device */
  263. {
  264.     register ReturnStatus error;
  265.     register DevSCSIController *scsiPtr;/* SCSI specific controller state */
  266.     register DevSCSIDevice *devPtr;    /* Device specific state */
  267.  
  268.     if (devConfPtr->flags == DEV_SCSI_DISK) {
  269. #ifdef SCSI_DISK_BOOT
  270.     scsiDiskIndex++;
  271. #else
  272.     return(FALSE);
  273. #endif
  274.     } else if (devConfPtr->flags == DEV_SCSI_TAPE) {
  275. #ifdef SCSI_TAPE_BOOT
  276.     scsiTapeIndex++;
  277. #else
  278.     return(FALSE);
  279. #endif
  280.     }
  281.  
  282.     scsiPtr = scsi[devConfPtr->controllerID];
  283.     if (scsiPtr == (DevSCSIController *)NIL) {
  284.     return(FALSE);
  285.     }
  286.  
  287.     devPtr = (DevSCSIDevice *)Mem_Alloc(sizeof(DevSCSIDevice));
  288.     devPtr->scsiPtr = scsiPtr;
  289.     devPtr->subUnitID = 0;
  290.     devPtr->slaveID = devConfPtr->slaveID;
  291. #ifdef SCSI_DISK_BOOT
  292.     if (devConfPtr->flags == DEV_SCSI_DISK) {
  293.     register DevSCSIDisk *diskPtr;    /* State about the disk */
  294.  
  295.     devPtr->type = SCSI_DISK;
  296.     devPtr->errorProc = DevSCSIDiskError;
  297.     error = DevSCSITest(devPtr);
  298.     if (error != SUCCESS) {
  299.         Sys_Printf("SCSI no slave %d\n", devPtr->slaveID);
  300.         return(FALSE);
  301.     }
  302. #ifdef notdef
  303.     /*
  304.      * Set up a slot in the disk list.
  305.      */
  306.     if (scsiDiskIndex >= SCSI_MAX_DISKS) {
  307. #ifndef NO_PRINTF
  308.         Sys_Printf("SCSI: To many disks configured\n");
  309. #endif
  310.         return(FALSE);
  311.     }
  312. #endif notdef
  313.     diskPtr = (DevSCSIDisk *) Mem_Alloc(sizeof(DevSCSIDisk));
  314.     devPtr->data = (ClientData)diskPtr;
  315.     scsiDisk[scsiDiskIndex] = devPtr;
  316.     DevSCSIDoLabel(devPtr);
  317.     }
  318. #endif SCSI_DISK_BOOT
  319. #ifdef SCSI_TAPE_BOOT
  320.     if (devConfPtr->flags == DEV_SCSI_TAPE) {
  321.     register DevSCSITape *tapePtr;    /* State about the drive */
  322.  
  323.     if (scsiTapeIndex >= SCSI_MAX_TAPES) {
  324. #ifndef NO_PRINTF
  325.         Sys_Printf("SCSI: To many tape drives configured\n");
  326. #endif
  327.         return(FALSE);
  328.     }
  329.     devPtr->type = SCSI_TAPE;
  330.     devPtr->errorProc = DevSCSITapeError;
  331.     tapePtr = (DevSCSITape *) Mem_Alloc(sizeof(DevSCSITape));
  332.     devPtr->data = (ClientData)tapePtr;
  333.     tapePtr->state = SCSI_TAPE_CLOSED;
  334.     tapePtr->type = SCSI_UNKNOWN;
  335.     scsiTape[scsiTapeIndex] = devPtr;
  336.     Sys_Printf("SCSI-%d tape %d at slave %d\n", scsiPtr->number,
  337.                 scsiTapeIndex, devPtr->slaveID);
  338.     }
  339. #endif SCSI_TAPE_BOOT
  340.     return(TRUE);
  341. }
  342.  
  343. /*
  344.  *----------------------------------------------------------------------
  345.  *
  346.  * DevSCSIReset --
  347.  *
  348.  *    Reset the controller.
  349.  *
  350.  * Results:
  351.  *    None.
  352.  *
  353.  * Side effects:
  354.  *    Reset the controller.
  355.  *
  356.  *----------------------------------------------------------------------
  357.  */
  358. void
  359. DevSCSIReset(regsPtr)
  360.     register DevSCSIRegs *regsPtr;
  361. {
  362.     regsPtr->control = SCSI_RESET;
  363.     MACH_DELAY(100);
  364.     regsPtr->control = 0;
  365. }
  366.  
  367. /*
  368.  *----------------------------------------------------------------------
  369.  *
  370.  * DevSCSITest --
  371.  *
  372.  *    Test an SCSI device to see if it is ready.
  373.  *
  374.  * Results:
  375.  *    SUCCESS if the device is ok, DEV_OFFLINE otherwise.
  376.  *
  377.  * Side effects:
  378.  *    none.
  379.  *
  380.  *----------------------------------------------------------------------
  381.  */
  382. ReturnStatus
  383. DevSCSITest(devPtr)
  384.     register DevSCSIDevice *devPtr;
  385. {
  386.     register ReturnStatus status;
  387.  
  388.     DevSCSISetupCommand(SCSI_TEST_UNIT_READY, devPtr, 0, 0);
  389.  
  390.     status = DevSCSICommand(devPtr->slaveID, devPtr->scsiPtr, 0, (Address)0);
  391.     if (status == DEV_TIMEOUT) {
  392.     status = DEV_OFFLINE;
  393.     }
  394.     return(status);
  395. }
  396.  
  397. /*
  398.  *----------------------------------------------------------------------
  399.  *
  400.  * DevSCSIDoLabel --
  401.  *
  402.  *    Read the label of the disk and record the partitioning info.
  403.  *
  404.  * Results:
  405.  *    None.
  406.  *
  407.  * Side effects:
  408.  *    Define the disk partitions that determine which part of the
  409.  *    disk each different disk device uses.
  410.  *
  411.  *----------------------------------------------------------------------
  412.  */
  413. #ifdef SCSI_DISK_BOOT
  414. void
  415. DevSCSIDoLabel(devPtr)
  416.     register DevSCSIDevice *devPtr;
  417. {
  418.     register DevSCSIController *scsiPtr = devPtr->scsiPtr;
  419.     register DevSCSIDisk *diskPtr;
  420.     register Address labelBuffer;
  421.     register int part;
  422.  
  423. #ifndef NO_PRINTF
  424.     Sys_Printf("SCSI-%d disk%d: ", scsiPtr->number, devPtr->slaveID);
  425. #endif
  426.  
  427.     DevSCSISetupCommand(SCSI_READ, devPtr, 0, 1);
  428.     labelBuffer = scsiPtr->labelBuffer;
  429.     (void)DevSCSICommand(devPtr->slaveID, scsiPtr, DEV_BYTES_PER_SECTOR,
  430.                          labelBuffer);
  431.     Sys_Printf("%s\n", labelBuffer);
  432.     diskPtr = (DevSCSIDisk *)devPtr->data;
  433.     if (((Sun_DiskLabel *)labelBuffer)->magic == SUN_DISK_MAGIC) {
  434.     register Sun_DiskLabel *sunLabelPtr;
  435.     sunLabelPtr = (Sun_DiskLabel *)labelBuffer;
  436.     diskPtr->numCylinders = sunLabelPtr->numCylinders;
  437.     diskPtr->numHeads = sunLabelPtr->numHeads;
  438.     diskPtr->numSectors = sunLabelPtr->numSectors;
  439.     for (part = 0; part < DEV_NUM_DISK_PARTS; part++) {
  440.         diskPtr->map[part].firstCylinder =
  441.             sunLabelPtr->map[part].cylinder;
  442.         diskPtr->map[part].numCylinders =
  443.             sunLabelPtr->map[part].numBlocks /
  444.             (sunLabelPtr->numHeads * sunLabelPtr->numSectors) ;
  445.     }
  446. #ifdef notdef
  447.     } else if (Fs_IsSpriteLabel(labelBuffer)) {
  448.     /*
  449.      * Probably shouldn't ever go to a different label.
  450.      */
  451.     register FsDiskHeader *diskHeaderPtr;
  452.     diskPtr->numCylinders = diskHeaderPtr->numCylinders;
  453.     diskPtr->numHeads = diskHeaderPtr->numHeads;
  454.     diskPtr->numSectors = diskHeaderPtr->numSectors;
  455.     for (part = 0; part < DEV_NUM_DISK_PARTS; part++) {
  456.         diskPtr->map[part].firstCylinder =
  457.             diskHeaderPtr->map[part].firstCylinder;
  458.         diskPtr->map[part].numCylinders =
  459.             diskHeaderPtr->map[part].numCylinders;
  460.     }
  461. #endif notdef
  462.     } else {
  463.     Sys_Printf("No Label\n");
  464.     return;
  465.     }
  466. }
  467. #endif SCSI_DISK_BOOT
  468.  
  469. /*
  470.  *----------------------------------------------------------------------
  471.  *
  472.  * Dev_SCSIDiskIO --
  473.  *
  474.  *      Read or Write (to/from) a raw SCSI disk file.  The deviceUnit
  475.  *      number is mapped to a particular partition on a particular disk.
  476.  *
  477.  * Results:
  478.  *    None.
  479.  *
  480.  * Side effects:
  481.  *    The IO
  482.  *
  483.  *----------------------------------------------------------------------
  484.  */
  485. #ifdef SCSI_DISK_BOOT
  486. ReturnStatus
  487. Dev_SCSIDiskIO(command, deviceUnit, buffer, firstSector, numSectorsPtr)
  488.     int command;            /* FS_READ or FS_WRITE */
  489.     int deviceUnit;            /* Unit from the filesystem that
  490.                      * indicates a disk and partition */
  491.     register char *buffer;        /* Target buffer */
  492.     int firstSector;            /* First sector to transfer */
  493.     int *numSectorsPtr;            /* Upon entry, the number of sectors to
  494.                      * transfer.  Upon return, the number
  495.                      * of sectors actually transferred. */
  496. {
  497.     register ReturnStatus error;
  498.     register DevSCSIDevice *devPtr;    /* Generic SCSI device state */
  499.     register DevSCSIDisk *diskPtr;    /* State of the disk */
  500.     register int totalSectors;    /* The total number of sectors to transfer */
  501.     int numSectors;        /* The number of sectors to transfer at
  502.                  * one time, up to a blocks worth. */
  503.     register int sectorZero;    /* Zero-th sector of the partition */
  504.     register int totalRead;    /* The total number of sectors transferred */
  505.  
  506.     /*
  507.      * Do no bounds checking.  If boot programs write the disk, then
  508.      * this should be reconsidered.
  509.      */
  510.     devPtr = scsiDisk[deviceUnit / DEV_NUM_DISK_PARTS];
  511.     diskPtr = (DevSCSIDisk *)devPtr->data;
  512.     sectorZero = diskPtr->map[deviceUnit % DEV_NUM_DISK_PARTS].firstCylinder *
  513.          (diskPtr->numHeads * diskPtr->numSectors);
  514.     totalSectors = *numSectorsPtr;
  515.     /*
  516.      * Chop up the IO into blocksize pieces.
  517.      */
  518.     totalRead = 0;
  519.     do {
  520.     if (totalSectors > SECTORS_PER_BLOCK) {
  521.         numSectors = SECTORS_PER_BLOCK;
  522.     } else {
  523.         numSectors = totalSectors;
  524.     }
  525.     error = DevSCSISectorIO((command == FS_WRITE) ? SCSI_WRITE : SCSI_READ,
  526.                 devPtr, sectorZero + firstSector,
  527.                 &numSectors, buffer);
  528.     if (error == SUCCESS) {
  529.         firstSector += numSectors;
  530.         totalSectors -= numSectors;
  531.         buffer += numSectors * DEV_BYTES_PER_SECTOR;
  532.         totalRead += numSectors;
  533.     }
  534.     } while (error == SUCCESS && totalSectors > 0);
  535.     *numSectorsPtr = totalRead;
  536.  
  537.     return(error);
  538. }
  539. #endif SCSI_DISK_BOOT
  540.  
  541. /*
  542.  *----------------------------------------------------------------------
  543.  *
  544.  * DevSCSISectorIO --
  545.  *
  546.  *      Lower level routine to read or write an SCSI device.  The
  547.  *      interface here is in terms of a particular SCSI disk and the
  548.  *      number of sectors to transfer.  This routine takes care of mapping
  549.  *      its buffer into the special multibus memory area that is set up
  550.  *      for Sun DMA.
  551.  *
  552.  * Results:
  553.  *    None.
  554.  *
  555.  * Side effects:
  556.  *    None.
  557.  *
  558.  *----------------------------------------------------------------------
  559.  */
  560. #ifdef SCSI_DISK_BOOT
  561. ReturnStatus
  562. DevSCSISectorIO(command, devPtr, firstSector, numSectorsPtr, buffer)
  563.     int command;            /* SCSI_READ or SCSI_WRITE */
  564.     register DevSCSIDevice *devPtr;    /* Which disk to do I/O with */
  565.     int firstSector;            /* The sector at which the transfer
  566.                      * begins. */
  567.     int *numSectorsPtr;            /* Upon entry, the number of sectors to
  568.                      * transfer.  Upon return, the number
  569.                      * of sectors transferred. */
  570.     register char *buffer;        /* Target buffer */
  571. {
  572.     register ReturnStatus error;
  573.     register DevSCSIController *scsiPtr; /* Controller for the disk */
  574.     register int numSectors;
  575.  
  576.     scsiPtr = devPtr->scsiPtr;
  577.     numSectors = *numSectorsPtr;
  578.  
  579.     /*
  580.      * Map the buffer into the special area of multibus memory that
  581.      * the device can DMA into.
  582.      */
  583.  
  584.     buffer = (char *)Vm_DevBufferMap(numSectors * DEV_BYTES_PER_SECTOR,
  585.                  buffer, scsiPtr->IOBuffer);
  586.     DevSCSISetupCommand(command, devPtr, firstSector, numSectors);
  587.     error = DevSCSICommand(devPtr->slaveID, scsiPtr,
  588.                  numSectors * DEV_BYTES_PER_SECTOR,
  589.                  buffer);
  590.  
  591.     *numSectorsPtr = numSectors - (scsiPtr->residual / DEV_BYTES_PER_SECTOR);
  592.     if (scsiPtr->flags & SCSI_IO_ERROR) {
  593.     scsiPtr->flags &= ~SCSI_IO_ERROR;
  594.     error = DEV_DMA_FAULT;
  595.     }
  596.     return(error);
  597. }
  598. #endif SCSI_DISK_BOOT
  599.  
  600. /*
  601.  *----------------------------------------------------------------------
  602.  *
  603.  * DevSCSITapeIO --
  604.  *
  605.  *      Read or Write (to/from) a raw SCSI tape file.  Like Dev_SCSIDiskIO
  606.  *    this maps to the SCSI state for the tape drive, then it does
  607.  *    the same sort of thing that DevSCSISectorIO does to do the IO.
  608.  *
  609.  * Results:
  610.  *    An error code.
  611.  *
  612.  * Side effects:
  613.  *    The IO
  614.  *
  615.  *----------------------------------------------------------------------
  616.  */
  617. #ifdef SCSI_TAPE_BOOT
  618. ReturnStatus
  619. DevSCSITapeIO(command, devPtr, buffer, countPtr)
  620.     int command;        /* SCSI_READ, SCSI_WRITE, SCSI_REWIND */
  621.     register DevSCSIDevice *devPtr;    /* Generic SCSI device state */
  622.     register char *buffer;    /* Target buffer */
  623.     int *countPtr;        /* Upon entry, the number of sectors to
  624.                  * transfer.  Upon return, the number
  625.                  * of sectors actually transferred. */
  626. {
  627.     register ReturnStatus error;
  628.     register DevSCSIController *scsiPtr; /* Controller for the drive */
  629.     register DevSCSITape *tapePtr;     /* State for the drive */
  630.  
  631.     scsiPtr = devPtr->scsiPtr;
  632.     tapePtr = (DevSCSITape *)devPtr->data;
  633.  
  634.     /*
  635.      * Map the buffer into the special area of multibus memory that
  636.      * the device can DMA into.
  637.      */
  638.  
  639.     if (command == SCSI_READ || command == SCSI_WRITE) {
  640.     buffer = Vm_DevBufferMap(*countPtr * DEV_BYTES_PER_SECTOR,
  641.                  buffer, scsiPtr->IOBuffer);
  642.     }
  643.     DevSCSISetupTapeCommand(command, devPtr, countPtr);
  644.     error = DevSCSICommand(devPtr->slaveID, scsiPtr, *countPtr, buffer);
  645.  
  646.     if (scsiPtr->residual) {
  647.     Sys_Printf("Residual %d\n", scsiPtr->residual);
  648.     }
  649.     *countPtr -= scsiPtr->residual;
  650.     if (command == SCSI_READ || command == SCSI_WRITE) {
  651.     *countPtr /= DEV_BYTES_PER_SECTOR;
  652.     }
  653.     if (scsiPtr->flags & SCSI_IO_ERROR) {
  654.     scsiPtr->flags &= ~SCSI_IO_ERROR;
  655.     error = DEV_DMA_FAULT;
  656.     Sys_Printf("IO ERROR\n");
  657.     }
  658.     return(error);
  659. }
  660. #endif SCSI_TAPE_BOOT
  661.  
  662. /*
  663.  *----------------------------------------------------------------------
  664.  *
  665.  * DevSCSISetupCommand --
  666.  *
  667.  *      Setup a control block for a command.  The control block can then
  668.  *      be passed to DevSCSICommand.  The control block specifies the a
  669.  *      sub-unit to the controller, the command, and the device address of
  670.  *      the transfer.
  671.  *
  672.  * Results:
  673.  *    None.
  674.  *
  675.  * Side effects:
  676.  *    Set the various fields in the control block.
  677.  *
  678.  *----------------------------------------------------------------------
  679.  */
  680. void
  681. DevSCSISetupCommand(command, devPtr, blockNumber, numSectors)
  682.     char command;        /* One of six standard SCSI commands */
  683.     register DevSCSIDevice *devPtr;    /* Device state */
  684.     register int blockNumber;    /* The starting block number for the transfer */
  685.     int numSectors;        /* Number of sectors to transfer */
  686. {
  687.     register DevSCSIControlBlock *controlBlockPtr;
  688.  
  689.     devPtr->scsiPtr->devPtr = devPtr;
  690.     controlBlockPtr = &devPtr->scsiPtr->controlBlock;
  691.     Byte_Zero(sizeof(DevSCSIControlBlock), (Address)controlBlockPtr);
  692.     controlBlockPtr->command = command;
  693.     controlBlockPtr->unitNumber = devPtr->subUnitID;
  694.     controlBlockPtr->highAddr = (blockNumber & 0x1f0000) >> 16;
  695.     controlBlockPtr->midAddr =  (blockNumber & 0x00ff00) >> 8;
  696.     controlBlockPtr->lowAddr =  (blockNumber & 0x0000ff);
  697.     controlBlockPtr->blockCount =  numSectors;
  698. }
  699.  
  700. /*
  701.  *----------------------------------------------------------------------
  702.  *
  703.  * DevSCSISetupTapeCommand --
  704.  *
  705.  *      A variation on DevSCSISetupCommand that creates a control block
  706.  *      designed for tape drives.  SCSI tape drives read from the current
  707.  *      tape position, so there is only a block count, no offset.
  708.  *
  709.  * Results:
  710.  *      None.
  711.  *
  712.  * Side effects:
  713.  *      Set the various fields in the tape control block.
  714.  *
  715.  *----------------------------------------------------------------------
  716.  */
  717. #ifdef SCSI_TAPE_BOOT
  718. void
  719. DevSCSISetupTapeCommand(command, devPtr, countPtr)
  720.     register int command;       /* One of standard SCSI commands */
  721.     register DevSCSIDevice *devPtr;    /* Device state */
  722.     int *countPtr;    /* In - Transfer count, bytes or sectors!
  723.              * Out - The proper dma byte count for our caller */
  724. {
  725.     register DevSCSITapeControlBlock *tapeControlBlockPtr;
  726.     register DevSCSITape *tapePtr;
  727.     register int code = 0;
  728.     register int dmaCount = *countPtr;
  729.     register int count = *countPtr;
  730.     register int type;
  731.  
  732.     devPtr->scsiPtr->devPtr = devPtr;
  733.     tapeControlBlockPtr =
  734.         (DevSCSITapeControlBlock *)&devPtr->scsiPtr->controlBlock;
  735.     Byte_Zero(sizeof(DevSCSITapeControlBlock), (Address)tapeControlBlockPtr);
  736.     tapePtr = (DevSCSITape *)devPtr->data;
  737.     type = tapePtr->type;
  738.  
  739.     /*
  740.      * Do per command/per controller initialization of the code field
  741.      * and the transfer count, and the return count used for DMA.
  742.      */
  743.     switch (command) {
  744.     case SCSI_TEST_UNIT_READY:
  745.         break;
  746.     case SCSI_REWIND:
  747.         if (tapePtr->state & SCSI_TAPE_RETENSION) {
  748.         if (type == SCSI_SYSGEN) {
  749.             tapeControlBlockPtr->vendor57 = 1;
  750.         } else {
  751.             command = SCSI_START_STOP;
  752.             dmaCount = 0;
  753.             count = 3;
  754.         }
  755.         tapePtr->state &= ~SCSI_TAPE_RETENSION;
  756.         }
  757.         tapePtr->state &= ~SCSI_TAPE_AT_EOF;
  758.         break;
  759.     case SCSI_REQUEST_SENSE:
  760.         if (type == SCSI_SYSGEN) {
  761.         dmaCount = count = sizeof(DevSCSISense);
  762.         } else {
  763.         dmaCount = count = sizeof(DevEmuluxSense);
  764.         }
  765.         break;
  766.     case SCSI_MODE_SELECT:
  767.         break;
  768.     case SCSI_READ:
  769.     case SCSI_WRITE:
  770.         dmaCount = count * DEV_BYTES_PER_SECTOR;
  771.         if (type == SCSI_EMULUX) {
  772.         code = 1;
  773.         }
  774.         break;
  775.     case SCSI_WRITE_EOF:
  776.         dmaCount = 0;
  777.         count = 1;
  778.         break;
  779.     case SCSI_SPACE:
  780.     case SCSI_SPACE_FILES:
  781.         dmaCount = 0;
  782.         code = 1;
  783.         command = SCSI_SPACE;
  784.         tapePtr->state &= ~SCSI_TAPE_AT_EOF;
  785.         break;
  786.     case SCSI_SPACE_BLOCKS:
  787.         dmaCount = 0;
  788.         code = 0;
  789.         command = SCSI_SPACE;
  790.         break;
  791.     case SCSI_SPACE_EOT:
  792.         dmaCount = 0;
  793.         code = 3;
  794.         command = SCSI_SPACE;
  795.         tapePtr->state |= SCSI_TAPE_AT_EOF;
  796.         break;
  797.     case SCSI_ERASE_TAPE:
  798.         if (type == SCSI_EMULUX) {
  799.         code = 1;
  800.         }
  801.         break;
  802.     default:
  803.         Sys_Printf("Unknown command %x\n", command);
  804.         break;
  805.     }
  806.  
  807.     *countPtr = dmaCount;
  808.  
  809.     tapeControlBlockPtr->command = command & 0xff;
  810.     tapeControlBlockPtr->code = code;
  811.     tapeControlBlockPtr->unitNumber = 0;    /* not targetID */
  812.     tapeControlBlockPtr->highCount = (count & 0x1f0000) >> 16;
  813.     tapeControlBlockPtr->midCount =  (count & 0x00ff00) >> 8;
  814.     tapeControlBlockPtr->lowCount =  (count & 0x0000ff);
  815.  
  816. #ifndef NO_PRINTF
  817.     Sys_Printf("cmd %x, code %d, unit %d, count (%d, %d, %d) dma %d\n",
  818.             tapeControlBlockPtr->command, tapeControlBlockPtr->code,
  819.             tapeControlBlockPtr->unitNumber,
  820.             tapeControlBlockPtr->highCount,
  821.             tapeControlBlockPtr->midCount,
  822.             tapeControlBlockPtr->lowCount,
  823.             dmaCount);
  824. #endif
  825. }
  826. #endif SCSI_TAPE_BOOT
  827.  
  828. /*
  829.  *----------------------------------------------------------------------
  830.  *
  831.  * DevSCSICommand --
  832.  *
  833.  *      Send a command to a controller specified by targetID on the SCSI
  834.  *      bus controlled through scsiPtr.  The control block needs to have
  835.  *      been set up previously with DevSCSISetupCommand.  This waits
  836.  *      around for the command to complete and checks the status results
  837.  *      because its a boot version.
  838.  *
  839.  * Results:
  840.  *    An error code.
  841.  *
  842.  * Side effects:
  843.  *    Those of the command (Read, write etc.)
  844.  *
  845.  *----------------------------------------------------------------------
  846.  */
  847. ReturnStatus
  848. DevSCSICommand(targetID, scsiPtr, size, addr)
  849.     int targetID;            /* Id of the SCSI device to select */
  850.     register DevSCSIController *scsiPtr;/* The SCSI controller that will be
  851.                      * doing the command. The control block
  852.                      * within this specifies the unit
  853.                      * number and device address of the
  854.                      * transfer */
  855.     int size;                /* Number of bytes to transfer */
  856.     Address addr;            /* Kernel address of transfer */
  857. {
  858.     register ReturnStatus error;
  859.     register DevSCSIRegs *regsPtr;    /* Host Adaptor registers */
  860.     register char *charPtr;        /* Used to put the control block
  861.                      * into the commandStatus register */
  862.     register int retries = 0;        /* Number of times command retried */
  863.     register int i;
  864.  
  865.     scsiPtr->command = scsiPtr->controlBlock.command;
  866.     /*
  867.      * Select the device.  Sun's SCSI Programmer's Manual recommends
  868.      * resetting the SCSI_WORD_MODE bit so that the byte packing hardware
  869.      * is reset and the data byte that has the target ID gets transfered
  870.      * correctly.  After this, the target's ID is put in the data register,
  871.      * the SELECT bit is set, and we wait until the device responds
  872.      * by setting the BUSY bit.  The ID bit of the host adaptor is not
  873.      * put in the data word because of problems with Sun's Host Adaptor.
  874.      */
  875. retry:
  876.     regsPtr = scsiPtr->regsPtr;
  877.     regsPtr->control = 0;
  878.     regsPtr->data = (1 << targetID);
  879.     regsPtr->control = SCSI_SELECT;
  880.     error = DevSCSIWait(regsPtr, SCSI_BUSY);
  881.     if (error != SUCCESS) {
  882.     regsPtr->data = 0;
  883.     regsPtr->control = 0;
  884.     if (scsiPtr->controlBlock.command != SCSI_TEST_UNIT_READY) {
  885. #ifndef NO_PRINTF
  886.         Sys_Printf("SCSI-%d: can't select slave %d\n", 
  887.                  scsiPtr->number, targetID);
  888. #endif
  889.     }
  890.     return(error);
  891.     }
  892.     /*
  893.      * Set up the interface's registers for the transfer.  The DMA address
  894.      * is relative to the multibus memory so the kernel's base address
  895.      * for multibus memory is subtracted from 'addr'. The host adaptor
  896.      * increments the dmaCount register until it reaches -1, hence the
  897.      * funny initialization. See page 4 of Sun's SCSI Prog. Manual.
  898.      */
  899.     regsPtr->dmaAddress = (int)(addr - DEV_MULTIBUS_BASE);
  900.     regsPtr->dmaCount = -size - 1;
  901.     regsPtr->control = SCSI_WORD_MODE|SCSI_DMA_ENABLE;
  902.  
  903.     /*
  904.      * Stuff the control block through the commandStatus register.
  905.      * The handshake on the SCSI bus is visible here:  we have to
  906.      * wait for the Request line on the SCSI bus to be raised before
  907.      * we can send the next command byte to the controller.  All commands
  908.      * are of "group 0" which means they are 6 bytes long.
  909.      */
  910.     charPtr = (char *)&scsiPtr->controlBlock;
  911.     for (i=0 ; i<sizeof(DevSCSIControlBlock) ; i++) {
  912.     error = DevSCSIWait(regsPtr, SCSI_REQUEST);
  913.     if (error != SUCCESS) {
  914. #ifndef NO_PRINTF
  915.         Sys_Printf("SCSI-%d: couldn't send command block (i=%d)\n",
  916.                  scsiPtr->number, i);
  917. #endif
  918.         return(error);
  919.     }
  920.     /*
  921.      * The device keeps the Control/Data line set while it
  922.      * is accepting control block bytes.
  923.      */
  924.     if ((regsPtr->control & SCSI_COMMAND) == 0) {
  925.         DevSCSIReset(regsPtr);
  926. #ifndef NO_PRINTF
  927.         Sys_Printf("SCSI-%d: device dropped command line\n",
  928.                  scsiPtr->number);
  929. #endif
  930.         return(DEV_HANDSHAKE_ERROR);
  931.     }
  932.     regsPtr->commandStatus = *charPtr;
  933.     charPtr++;
  934.     }
  935.     /*
  936.      * Always use synchronous commands.  Wait here for the command to complete.
  937.      * We don't check for odd lenth transfers like the kernel DevSCSIIntr().
  938.      */
  939.     error = DevSCSIWait(regsPtr, SCSI_INTERRUPT_REQUEST);
  940.     if (error == SUCCESS) {
  941.     scsiPtr->residual = -regsPtr->dmaCount -1;
  942.     error = DevSCSIStatus(scsiPtr);
  943.     } else if (regsPtr->control & SCSI_BUS_ERROR) {
  944.     if (regsPtr->dmaCount >= 0) {
  945.         /*
  946.          * DMA overrun.
  947.          */
  948. #ifndef NO_PRINTF
  949.         Sys_Printf("SCSI-%d %d: DMA Overrun\n", scsiPtr->number, targetID);
  950. #endif NO_PRINTF
  951.         scsiPtr->residual = 0;
  952.     } else {
  953.         /*
  954.          * Bona-fide bus error.
  955.          */
  956.         scsiPtr->residual = -regsPtr->dmaCount -1;
  957.         scsiPtr->flags |= SCSI_IO_ERROR;
  958.     }
  959.     /*
  960.      * In either case have to reset to clear the bus error condition.
  961.      */
  962.     DevSCSIReset(regsPtr);
  963.     }
  964.     if ((error == DEV_RETRY_ERROR) && (++retries < 5)) {
  965. #ifndef NO_PRINTF
  966.     Sys_Printf("SCSI-%d %d: retry (%d, %x)\n",
  967.                 scsiPtr->number, targetID, size, addr);
  968. #endif NO_PRINTF
  969.     goto retry;
  970.     }
  971.     return(error);
  972. }
  973.  
  974. /*
  975.  *----------------------------------------------------------------------
  976.  *
  977.  * DevSCSIStatus --
  978.  *
  979.  *    Complete an SCSI command by getting the status bytes from
  980.  *    the device and waiting for the ``command complete''
  981.  *    message that follows the status bytes.  If the command has
  982.  *    additional ``sense data'' then this routine issues the
  983.  *    SCSI_REQUEST_SENSE command to get the sense data.
  984.  *
  985.  * Results:
  986.  *    An error code if the status didn't come through or it
  987.  *    indicated an error.
  988.  *
  989.  * Side effects:
  990.  *    None.
  991.  *
  992.  *----------------------------------------------------------------------
  993.  */
  994. ReturnStatus
  995. DevSCSIStatus(scsiPtr)
  996.     DevSCSIController *scsiPtr;
  997. {
  998.     register ReturnStatus error;
  999.     register DevSCSIRegs *regsPtr;
  1000.     register short message;
  1001.     register char status;
  1002.     register char *statusBytePtr;
  1003.     register int numStatusBytes = 0;
  1004.  
  1005.     regsPtr = scsiPtr->regsPtr;
  1006.     statusBytePtr = (char *)&scsiPtr->statusBlock;
  1007.     Byte_Zero(sizeof(DevSCSIStatusBlock), (Address)statusBytePtr);
  1008.     for ( ; ; ) {
  1009.     /*
  1010.      * Could probably wait either on the INTERUPT_REQUEST bit or the
  1011.      * REQUEST bit.  Reading the byte out of the commandStatus
  1012.      * register acknowledges the REQUEST and clears these bits.  Here
  1013.      * we grab bytes until the MESSAGE bit indicates that all the
  1014.      * status bytes have been received and that the byte in the
  1015.      * commandStatus register is the message byte.
  1016.      */
  1017.     error = DevSCSIWait(regsPtr, SCSI_REQUEST);
  1018.     if (error != SUCCESS) {
  1019. #ifndef NO_PRINTF
  1020.         Sys_Printf("SCSI-%d: wait error after %d status bytes\n",
  1021.                  scsiPtr->number, numStatusBytes);
  1022. #endif
  1023.         break;
  1024.     }
  1025.     if (regsPtr->control & SCSI_MESSAGE) {
  1026.         message = regsPtr->commandStatus & 0xff;
  1027. #ifndef NO_PRINTF
  1028.         if (message != SCSI_COMMAND_COMPLETE) {
  1029.         Sys_Printf("SCSI-%d: Unexpected message 0x%x\n",
  1030.                      scsiPtr->number, message);
  1031.         }
  1032. #endif
  1033.         break;
  1034.     }  else {
  1035.         /*
  1036.          * This is another status byte.  Place the first few status
  1037.          * bytes into the status block.
  1038.          */
  1039.         status = regsPtr->commandStatus;
  1040.         if (numStatusBytes < sizeof(DevSCSIStatusBlock)) {
  1041.         *statusBytePtr = status;
  1042.         statusBytePtr++;
  1043.         }
  1044.         numStatusBytes++;
  1045.     }
  1046.     }
  1047.     if (error == SUCCESS) {
  1048.     /*
  1049.      * The status may indicate that further ``sense'' data is
  1050.      * available.  This is obtained by another SCSI command
  1051.      * that uses DMA to transfer the sense data.
  1052.      */
  1053.     if (scsiPtr->statusBlock.check) {
  1054.         error = DevSCSIRequestSense(scsiPtr, scsiPtr->devPtr);
  1055.     }
  1056.     }
  1057.     return(error);
  1058. }
  1059.  
  1060. /*
  1061.  *----------------------------------------------------------------------
  1062.  *
  1063.  * DevSCSIReqeustSense --
  1064.  *
  1065.  *    Do a request-sense command to obtain the sense data that an
  1066.  *    SCSI device returns after some error conditions.  Unfortunately,
  1067.  *    the format of the sense data varies with different controllers.
  1068.  *    The "sysgen" drive on 2/120's has a format described by
  1069.  *    the DevSCSITapeSense type, while the shoebox drives use the
  1070.  *    more standard error "class 7" format.
  1071.  *
  1072.  * Results:
  1073.  *    SUCCESS if the sense data is benign.
  1074.  *
  1075.  * Side effects:
  1076.  *    Does an SCSI_REQUEST_SENSE command.
  1077.  *
  1078.  *----------------------------------------------------------------------
  1079.  */
  1080. ReturnStatus
  1081. DevSCSIRequestSense(scsiPtr, devPtr)
  1082.     register DevSCSIController *scsiPtr;    /* Controller state */
  1083.     register DevSCSIDevice *devPtr;    /* Device state for error checking */
  1084. {
  1085.     register ReturnStatus status = SUCCESS;
  1086.     register DevSCSISense *sensePtr = scsiPtr->senseBuffer;
  1087.     register int command;
  1088.  
  1089.     if (scsiPtr->flags & SCSI_GETTING_STATUS) {
  1090. #ifndef NO_PRINTF
  1091.     Sys_Panic(SYS_WARNING, "DevSCSIRequestSense recursed");
  1092. #endif
  1093.     } else {
  1094.     /*
  1095.      * The regular SetupCommand procedure is used, although the
  1096.      * "numSectors" parameter needs to be a byte count...
  1097.      */
  1098.     scsiPtr->flags |= SCSI_GETTING_STATUS;
  1099.     command = scsiPtr->command;
  1100.     DevSCSISetupCommand(SCSI_REQUEST_SENSE, devPtr, 0,
  1101.                 sizeof(DevSCSISense));
  1102.     status = DevSCSICommand(devPtr->slaveID, scsiPtr, sizeof(DevSCSISense),
  1103.                 (Address)sensePtr);
  1104.     scsiPtr->command = command;
  1105.     scsiPtr->flags &= ~SCSI_GETTING_STATUS;
  1106. #ifdef SCSI_TAPE_BOOT
  1107.     if (devPtr->type == SCSI_TAPE &&
  1108.         ((DevSCSITape *)devPtr->data)->type == SCSI_UNKNOWN) {
  1109.         /*
  1110.          * Heuristically determine the drive type...  We ask for the max
  1111.          * possible sense bytes, and this gets returned by the sysgen
  1112.          * controller.  The emulux controller returns less.  We might
  1113.          * also be able to depend on the class7 sense class below...
  1114.          */
  1115.         Sys_Printf("RequestSense, residual is %d\n", scsiPtr->residual);
  1116.         if (scsiPtr->residual == 0) {
  1117.         ((DevSCSITape *)devPtr->data)->type = SCSI_SYSGEN;
  1118.         } else {
  1119.         ((DevSCSITape *)devPtr->data)->type = SCSI_EMULUX;
  1120.         }
  1121.     }
  1122. #endif SCSI_TAPE_BOOT
  1123.     status = (*devPtr->errorProc)(devPtr, sensePtr);
  1124.     }
  1125.     return(status);
  1126. }
  1127.  
  1128. /*
  1129.  *----------------------------------------------------------------------
  1130.  *
  1131.  * DevSCSIWait --
  1132.  *
  1133.  *    Wait for a condition in the SCSI controller.
  1134.  *
  1135.  * Results:
  1136.  *    SUCCESS if the condition occurred before a threashold time limit,
  1137.  *    DEV_TIMEOUT otherwise.
  1138.  *
  1139.  * Side effects:
  1140.  *    None.
  1141.  *
  1142.  *----------------------------------------------------------------------
  1143.  */
  1144. ReturnStatus
  1145. DevSCSIWait(regsPtr, condition)
  1146.     register DevSCSIRegs *regsPtr;
  1147.     register int condition;
  1148. {
  1149.     register int i;
  1150.     register ReturnStatus status = DEV_TIMEOUT;
  1151.  
  1152.     for (i=0 ; i<SCSI_WAIT_LENGTH ; i++) {
  1153.     if (regsPtr->control & condition) {
  1154.         return(SUCCESS);
  1155.     } else if (regsPtr->control & SCSI_BUS_ERROR) {
  1156.         Sys_Printf("SCSI: bus error\n");
  1157.         status = DEV_DMA_FAULT;
  1158.         break;
  1159.     }
  1160.     MACH_DELAY(10);
  1161.     }
  1162.     DevSCSIReset(regsPtr);
  1163.     return(status);
  1164. }
  1165. @
  1166.  
  1167.  
  1168. 1.8
  1169. log
  1170. @Update driver to handle controller vector number
  1171. @
  1172. text
  1173. @d18 1
  1174. a18 1
  1175. static char rcsid[] = "$Header: devSCSI.c,v 1.7 87/05/12 12:45:35 brent Exp $ SPRITE (Berkeley)";
  1176. d28 2
  1177. a29 3
  1178. #include "multibus.h"
  1179. #include "sunMon.h"
  1180. #include "sunDiskLabel.h"
  1181. d34 2
  1182. a35 1
  1183. #include "machine.h"
  1184. d40 1
  1185. a40 2
  1186. #define Sys_Printf Mon_Printf
  1187. #include "sunMon.h"
  1188. d299 1
  1189. a299 1
  1190.     DELAY(100);
  1191. d520 1
  1192. a520 1
  1193.     buffer = Vm_DevBufferMap(numSectors * DEV_BYTES_PER_SECTOR,
  1194. d835 1
  1195. a835 1
  1196.     regsPtr->dmaAddress = (int)(addr - MULTIBUS_BASE);
  1197. d1096 1
  1198. a1096 1
  1199.     DELAY(10);
  1200. @
  1201.  
  1202.  
  1203. 1.7
  1204. log
  1205. @Working version for scsi disk and tape
  1206. @
  1207. text
  1208. @d18 1
  1209. a18 1
  1210. static char rcsid[] = "$Header: devSCSI.c,v 1.6 87/05/11 11:11:30 brent Exp $ SPRITE (Berkeley)";
  1211. d149 1
  1212. a149 1
  1213.  
  1214. @
  1215.  
  1216.  
  1217. 1.6
  1218. log
  1219. @Trimmed down version that works for disk boot
  1220. @
  1221. text
  1222. @d18 1
  1223. a18 1
  1224. static char rcsid[] = "$Header: devSCSI.c,v 1.5 87/05/08 17:42:55 brent Exp $ SPRITE (Berkeley)";
  1225. d540 1
  1226. a540 1
  1227.  * Dev_SCSITapeIO --
  1228. d556 1
  1229. a556 1
  1230. Dev_SCSITapeIO(command, devPtr, buffer, countPtr)
  1231. a578 3
  1232. #ifndef NO_PRINTF
  1233.     Sys_Printf("mapped buffer %x\n", buffer);
  1234. #endif NO_PRINTF
  1235. d583 3
  1236. d657 1
  1237. a657 1
  1238.     register char command;       /* One of standard SCSI commands */
  1239. d739 3
  1240. d744 3
  1241. a746 1
  1242.     tapeControlBlockPtr->command = command;
  1243. d753 2
  1244. a754 1
  1245.     Sys_Printf("cmd %d, code %d, unit %d, count (%d, %d, %d)\n",
  1246. d759 3
  1247. a761 1
  1248.             tapeControlBlockPtr->lowCount);
  1249. @
  1250.  
  1251.  
  1252. 1.5
  1253. log
  1254. @Converted to new interfaces added to main kernel version.
  1255. @
  1256. text
  1257. @d18 1
  1258. a18 1
  1259. static char rcsid[] = "$Header: devSCSI.c,v 1.4 86/07/24 11:26:35 brent Exp $ SPRITE (Berkeley)";
  1260. d112 1
  1261. a112 1
  1262.     DevConfigController *cntrlrPtr;    /* Config info for the controller */
  1263. d115 1
  1264. a115 1
  1265.     DevSCSIRegs *regsPtr;        /* Control registers for SCSI */
  1266. d180 5
  1267. a184 3
  1268.  *    Initialize a device hanging off an SCSI controller.
  1269.  *    This keeps track of how many times it is called with
  1270.  *    for disks and tapes so that it can properly correlate
  1271. d199 1
  1272. a199 1
  1273.     DevConfigDevice *devConfPtr;    /* Config info about the device */
  1274. d201 3
  1275. a203 3
  1276.     ReturnStatus error;
  1277.     DevSCSIController *scsiPtr;    /* SCSI specific controller state */
  1278.     DevSCSIDevice *devPtr;    /* Device specific state */
  1279. d230 1
  1280. a230 1
  1281.     DevSCSIDisk *diskPtr;    /* State about the disk we are initializing */
  1282. d258 1
  1283. a258 1
  1284.     DevSCSITape *tapePtr;    /* State about the drive we are initializing */
  1285. d297 1
  1286. a297 1
  1287.     DevSCSIRegs *regsPtr;
  1288. d321 1
  1289. a321 1
  1290.     DevSCSIDevice *devPtr;
  1291. d370 1
  1292. a370 1
  1293.     if (Fs_IsSunLabel(labelBuffer)) {
  1294. d501 1
  1295. a501 1
  1296.     DevSCSIDevice *devPtr;        /* Which disk to do I/O with */
  1297. d507 1
  1298. a507 1
  1299.     char *buffer;            /* Target buffer */
  1300. d509 1
  1301. a509 1
  1302.     ReturnStatus error;
  1303. d560 1
  1304. a560 1
  1305.     int *numSectorsPtr;        /* Upon entry, the number of sectors to
  1306. d564 1
  1307. a564 1
  1308.     ReturnStatus error;
  1309. a570 4
  1310.     Sys_Printf("TapeIO: tapePtr %x, scsiPtr %x\n", tapePtr, scsiPtr);
  1311.     Sys_Printf("TapeIO: unit %d, buffer %x, numSec %d, ",
  1312.             deviceUnit, buffer, numSectors);
  1313.  
  1314. d577 1
  1315. a577 1
  1316.     buffer = Vm_DevBufferMap(numSectors * DEV_BYTES_PER_SECTOR,
  1317. d579 1
  1318. d581 1
  1319. d657 1
  1320. a657 1
  1321.     char command;       /* One of six standard SCSI commands */
  1322. d663 2
  1323. a664 2
  1324.     register DevSCSItape *tapePtr;
  1325.     char code = 0;
  1326. d744 3
  1327. a746 3
  1328.     tapeControlBlockPtr->highCount = (numSectors & 0x1f0000) >> 16;
  1329.     tapeControlBlockPtr->midCount =  (numSectors & 0x00ff00) >> 8;
  1330.     tapeControlBlockPtr->lowCount =  (numSectors & 0x0000ff);
  1331. d779 1
  1332. a779 1
  1333.     DevSCSIController *scsiPtr;        /* The SCSI controller that will be
  1334. d1011 2
  1335. a1012 2
  1336.     DevSCSIController *scsiPtr;    /* Controller state */
  1337.     DevSCSIDevice *devPtr;    /* Device state needed for error checking */
  1338. d1014 1
  1339. a1014 1
  1340.     ReturnStatus status = SUCCESS;
  1341. d1016 1
  1342. a1016 1
  1343.     int command;
  1344. d1076 1
  1345. a1076 1
  1346.     int condition;
  1347. @
  1348.  
  1349.  
  1350. 1.4
  1351. log
  1352. @Had forgotten to initialize disk map!!!  Expanded sense error
  1353. print statement.  More triming with register variables.
  1354. @
  1355. text
  1356. @d18 1
  1357. a18 1
  1358. static char rcsid[] = "$Header: devSCSI.c,v 1.3 86/07/21 09:32:35 brent Exp $ SPRITE (Berkeley)";
  1359. d23 1
  1360. d54 2
  1361. a55 1
  1362. DevSCSIDisk *scsiDisk[SCSI_MAX_DISKS];
  1363. d57 1
  1364. a57 1
  1365. static Boolean scsiDiskInit = FALSE;
  1366. d59 6
  1367. d66 1
  1368. d71 1
  1369. a71 1
  1370. #define SECTORS_PER_BLOCK    (FS_BLOCK_SIZE / BYTES_PER_SECTOR)
  1371. d85 8
  1372. d166 1
  1373. a166 1
  1374.     scsiPtr->labelBuffer = (Address)Dev_IOAlloc(BYTES_PER_SECTOR);
  1375. d196 2
  1376. a197 2
  1377. Dev_SCSIInitDevice(devPtr)
  1378.     DevConfigDevice *devPtr;    /* Config info about the device */
  1379. d201 1
  1380. a201 1
  1381.     DevSCSIDisk *diskPtr;    /* State about the disk we are initializing */
  1382. d203 2
  1383. a204 1
  1384.     if (devPtr->flags == DEV_SCSI_DISK) {
  1385. d206 5
  1386. a210 1
  1387.     } else if (devPtr->flags == DEV_SCSI_TAPE) {
  1388. d212 3
  1389. d217 1
  1390. a217 1
  1391.     scsiPtr = scsi[devPtr->controllerID];
  1392. d222 16
  1393. a237 5
  1394.     error = DevSCSITest(scsiPtr, devPtr->slaveID);
  1395.     if (error != SUCCESS) {
  1396.     return(FALSE);
  1397.     }
  1398.     if (devPtr->flags == DEV_SCSI_DISK) {
  1399. d247 1
  1400. d249 3
  1401. a251 4
  1402.     diskPtr->scsiPtr = scsiPtr;
  1403.     diskPtr->slaveID = devPtr->slaveID;
  1404.     scsiDisk[scsiDiskIndex] = diskPtr;
  1405.     DevSCSIDoLabel(scsiPtr, diskPtr);
  1406. d253 22
  1407. d318 2
  1408. a319 3
  1409. DevSCSITest(scsiPtr, targetID)
  1410.     DevSCSIController *scsiPtr;
  1411.     int targetID;
  1412. d323 1
  1413. a323 2
  1414.     DevSCSISetupCommand(SCSI_TEST_UNIT_READY, targetID, 0, 0,
  1415.                           &scsiPtr->controlBlock);
  1416. d325 1
  1417. a325 1
  1418.     status = DevSCSICommand(targetID, scsiPtr, 0, (Address)0);
  1419. d348 1
  1420. d350 4
  1421. a353 2
  1422. DevSCSIDoLabel(scsiPtr, diskPtr)
  1423.     DevSCSIController *scsiPtr;
  1424. a354 1
  1425. {
  1426. d359 1
  1427. a359 1
  1428.     Sys_Printf("SCSI-%d disk%d: ", scsiPtr->number, diskPtr->slaveID);
  1429. d362 1
  1430. a362 2
  1431.     DevSCSISetupCommand(SCSI_READ, diskPtr->slaveID,
  1432.                    0, 1, &scsiPtr->controlBlock);
  1433. d364 1
  1434. a364 1
  1435.     (void)DevSCSICommand(diskPtr->slaveID, scsiPtr, BYTES_PER_SECTOR,
  1436. d367 1
  1437. d381 1
  1438. d383 3
  1439. d396 1
  1440. d402 1
  1441. d407 1
  1442. a407 1
  1443.  * Dev_SCSIIO --
  1444. d420 1
  1445. d422 1
  1446. a422 1
  1447. Dev_SCSIIO(command, deviceUnit, buffer, firstSector, numSectorsPtr)
  1448. d433 1
  1449. d445 2
  1450. a446 1
  1451.     diskPtr = scsiDisk[deviceUnit / DEV_NUM_DISK_PARTS];
  1452. d461 1
  1453. a461 1
  1454.                 diskPtr, sectorZero + firstSector,
  1455. d466 1
  1456. a466 1
  1457.         buffer += numSectors * BYTES_PER_SECTOR;
  1458. d474 1
  1459. d495 1
  1460. d497 1
  1461. a497 1
  1462. DevSCSISectorIO(command, diskPtr, firstSector, numSectorsPtr, buffer)
  1463. d499 1
  1464. a499 1
  1465.     DevSCSIDisk *diskPtr;        /* Which disk to do I/O with */
  1466. d511 1
  1467. a511 1
  1468.     scsiPtr = diskPtr->scsiPtr;
  1469. d519 1
  1470. a519 1
  1471.     buffer = Vm_DevBufferMap(numSectors * BYTES_PER_SECTOR,
  1472. d521 3
  1473. a523 4
  1474.     DevSCSISetupCommand(command, diskPtr->slaveID, firstSector, numSectors,
  1475.                    &scsiPtr->controlBlock);
  1476.     error = DevSCSICommand(diskPtr->slaveID, scsiPtr,
  1477.                  numSectors * BYTES_PER_SECTOR,
  1478. d526 1
  1479. a526 1
  1480.     *numSectorsPtr = numSectors - (scsiPtr->residual / BYTES_PER_SECTOR);
  1481. d533 1
  1482. d538 64
  1483. d618 1
  1484. a618 1
  1485. DevSCSISetupCommand(command, targetID, blockNumber, numSectors, controlBlockPtr)
  1486. d620 1
  1487. a620 1
  1488.     int targetID;        /* Spefifies unit within the controller */
  1489. d623 1
  1490. d625 3
  1491. a627 1
  1492. {
  1493. d630 1
  1494. a630 1
  1495.     controlBlockPtr->unitNumber = targetID;
  1496. d640 120
  1497. d794 1
  1498. a804 1
  1499.     scsiPtr->targetID = targetID;
  1500. d811 2
  1501. d865 1
  1502. a865 1
  1503.      * Always synchronous commands.  Wait here for the command to complete.
  1504. d877 3
  1505. d983 36
  1506. a1018 1
  1507.         if (scsiPtr->flags & SCSI_GETTING_STATUS) {
  1508. d1020 1
  1509. a1020 1
  1510.         Sys_Printf("SCSI-%d: DevSCSIStatus recursed\n", scsiPtr->number);
  1511. d1022 25
  1512. d1048 1
  1513. a1048 24
  1514.         scsiPtr->flags |= SCSI_GETTING_STATUS;
  1515.         DevSCSISetupCommand(SCSI_REQUEST_SENSE, scsiPtr->targetID, 0, 0,
  1516.                     &scsiPtr->controlBlock);
  1517.         status = DevSCSICommand(scsiPtr->targetID, scsiPtr,
  1518.                        sizeof(DevSCSISense),
  1519.                     (Address)scsiPtr->senseBuffer);
  1520.         scsiPtr->flags &= ~SCSI_GETTING_STATUS;
  1521.  
  1522.         /*
  1523.          * Unless the class and code are zero (meaning no sense data)
  1524.          * dump the sense info out for debugging.
  1525.          */
  1526.         if (scsiPtr->senseBuffer->class ||
  1527.             scsiPtr->senseBuffer->code) {
  1528.             register DevSCSISense *sensePtr = scsiPtr->senseBuffer;
  1529.             register unsigned int addr;
  1530.             addr = (sensePtr->highAddr << 16) |
  1531.                 (sensePtr->midAddr << 8) |
  1532.                 sensePtr->lowAddr;
  1533.             Sys_Printf("\nSCSI-%d: Sense error (%d-%d) <%x>\n",
  1534.                      scsiPtr->number, sensePtr->class,
  1535.                      sensePtr->code, addr);
  1536.             error = DEV_RETRY_ERROR;
  1537.         }
  1538. d1051 2
  1539. a1052 6
  1540. #ifndef NO_PRINTF
  1541.     if (scsiPtr->statusBlock.error) {
  1542.         Sys_Printf("SCSI-%d: host adaptor error bit set\n",
  1543.                  scsiPtr->number);
  1544.     }
  1545. #endif
  1546. d1054 1
  1547. a1054 1
  1548.     return(error);
  1549. @
  1550.  
  1551.  
  1552. 1.3
  1553. log
  1554. @Added in residual computation
  1555. @
  1556. text
  1557. @d11 1
  1558. a11 1
  1559.  *    2156    148     8       2312    908    devSCSI.o (-DNO_PRINTF)
  1560. d18 1
  1561. a18 1
  1562. static char rcsid[] = "$Header: devSCSI.c,v 1.2 86/07/18 13:06:04 brent Exp $ SPRITE (Berkeley)";
  1563. d99 1
  1564. a99 1
  1565.     int x;                /* Used when probing the controller */
  1566. a128 1
  1567.     Mem_Free((Address) scsiPtr);
  1568. d135 1
  1569. d137 1
  1570. d237 1
  1571. a237 1
  1572.     register DevSCSIRegs *regsPtr;
  1573. d295 1
  1574. a295 1
  1575.     DevSCSIDisk *diskPtr;
  1576. d298 1
  1577. a298 1
  1578.     int part;
  1579. d300 1
  1580. d302 1
  1581. d311 12
  1582. a322 3
  1583.     diskPtr->numCylinders = ((Sun_DiskLabel *)labelBuffer)->numCylinders;
  1584.     diskPtr->numHeads = ((Sun_DiskLabel *)labelBuffer)->numHeads;
  1585.     diskPtr->numSectors = ((Sun_DiskLabel *)labelBuffer)->numSectors;
  1586. d324 10
  1587. a333 3
  1588.     diskPtr->numCylinders = ((FsDiskHeader *)labelBuffer)->numCylinders;
  1589.     diskPtr->numHeads = ((FsDiskHeader *)labelBuffer)->numHeads;
  1590.     diskPtr->numSectors = ((FsDiskHeader *)labelBuffer)->numSectors;
  1591. d367 1
  1592. a367 2
  1593.     ReturnStatus error;
  1594.     int part;        /* Partition of disk that corresponds to unit number */
  1595. d369 1
  1596. a369 1
  1597.     int totalSectors;    /* The total number of sectors to transfer */
  1598. d372 2
  1599. a373 2
  1600.     int sectorZero;    /* Zero-th sector of the partition */
  1601.     int totalRead;    /* The total number of sectors actually transferred */
  1602. d404 1
  1603. d449 1
  1604. d533 1
  1605. a533 1
  1606.     char *charPtr;            /* Used to put the control block
  1607. d535 2
  1608. a536 1
  1609.     int i;
  1610. d547 1
  1611. d632 7
  1612. d735 16
  1613. a750 5
  1614. #ifndef NO_PRINTF
  1615.         Sys_Printf("SCSI-%d: Sense error (%d-%d)\n",
  1616.                      scsiPtr->senseBuffer->class,
  1617.                      scsiPtr->senseBuffer->code);
  1618. #endif
  1619. d785 1
  1620. a785 1
  1621.     ReturnStatus status = DEV_TIMEOUT;
  1622. @
  1623.  
  1624.  
  1625. 1.2
  1626. log
  1627. @Something funny, works without NO_PRINTF defined, but not
  1628. with it defined.
  1629. @
  1630. text
  1631. @d18 1
  1632. a18 1
  1633. static char rcsid[] = "$Header: devSCSI.c,v 1.9 86/07/15 10:55:32 brent Exp $ SPRITE (Berkeley)";
  1634. d40 1
  1635. a295 1
  1636. #ifdef notdef
  1637. a318 35
  1638. #else
  1639.     register ReturnStatus error;
  1640.     Sun_DiskLabel *diskLabelPtr;
  1641.     int part;
  1642.  
  1643.     DevSCSISetupCommand(SCSI_READ, diskPtr->slaveID,
  1644.                    0, 1, &scsiPtr->controlBlock);
  1645.  
  1646.     error = DevSCSICommand(diskPtr->slaveID, scsiPtr, BYTES_PER_SECTOR,
  1647.                          scsiPtr->labelBuffer);
  1648.     if (error != SUCCESS) {
  1649.     Sys_Printf("SCSI-%d disk%d: label read error <%x>\n",
  1650.                  scsiPtr->number, diskPtr->slaveID, error);
  1651.     return;
  1652.     }
  1653.     diskLabelPtr = (Sun_DiskLabel *)scsiPtr->labelBuffer;
  1654.     Sys_Printf("SCSI-%d disk%d: %s\n", scsiPtr->number, diskPtr->slaveID,
  1655.             diskLabelPtr->asciiLabel);
  1656.  
  1657.     diskPtr->numCylinders = diskLabelPtr->numCylinders;
  1658.     diskPtr->numHeads = diskLabelPtr->numHeads;
  1659.     diskPtr->numSectors = diskLabelPtr->numSectors;
  1660.  
  1661.     Sys_Printf(" Partitions ");
  1662.     for (part = 0; part < DEV_NUM_DISK_PARTS; part++) {
  1663.     diskPtr->map[part].firstCylinder =
  1664.         diskLabelPtr->map[part].cylinder;
  1665.     diskPtr->map[part].numCylinders =
  1666.         diskLabelPtr->map[part].numBlocks /
  1667.         (diskLabelPtr->numHeads * diskLabelPtr->numSectors) ;
  1668.     Sys_Printf(" (%d,%d)", diskPtr->map[part].firstCylinder,
  1669.                    diskPtr->map[part].numCylinders);
  1670.     }
  1671.     Sys_Printf("\n");
  1672. #endif
  1673. a327 2
  1674.  *    The transfer is checked against the partition size to
  1675.  *      make sure that the I/O doesn't cross a disk partition.
  1676. d333 1
  1677. a333 2
  1678.  *    The number of sectors to transfer gets trimmed down if it would
  1679.  *    cross into the next partition.
  1680. d586 1
  1681. d590 1
  1682. d592 12
  1683. a603 3
  1684.     if (error != SUCCESS) {
  1685.         Sys_Printf("SCSI-%d: error getting status\n",
  1686.                  scsiPtr->number);
  1687. d605 4
  1688. a608 3
  1689.     } else {
  1690.     Sys_Printf("SCSI-%d: couldn't wait for command to complete\n",
  1691.                  scsiPtr->number);
  1692. d665 1
  1693. a666 1
  1694.         message = regsPtr->commandStatus & 0xff;
  1695. @
  1696.  
  1697.  
  1698. 1.1
  1699. log
  1700. @Initial revision
  1701. @
  1702. text
  1703. @d7 6
  1704. a29 2
  1705. #include "dbg.h"
  1706. #include "vm.h"
  1707. a30 1
  1708. #include "proc.h"    /* for Sys_SetJump */
  1709. d32 1
  1710. a32 1
  1711. #include "mem.h"
  1712. d34 1
  1713. d37 5
  1714. a56 4
  1715. /*
  1716.  * SetJump stuff needed when probing for the existence of a device.
  1717.  */
  1718. static Sys_SetJumpState setJumpState;
  1719. a58 8
  1720.  * DevSCSICommand() takes a Boolean that indicates whether it should cause
  1721.  * an interupt when the command is complete or whether it should busy wait
  1722.  * until the command finishes.  These defines make the calls clearer.
  1723.  */
  1724. #define INTERRUPT    TRUE
  1725. #define WAIT        FALSE
  1726.  
  1727. /*
  1728. d96 2
  1729. a97 2
  1730.     DevSCSIController *scsiPtr;        /* SCSI specific state */
  1731.     register DevSCSIRegs *regsPtr;    /* Control registers for SCSI */
  1732. a108 12
  1733.      * Initialize the array of disk information to NIL because it
  1734.      * needs to be done somewhere.  Can also check against zero instead
  1735.      * of NIL and rely on load-time declaration.
  1736.      */
  1737.     if (!scsiDiskInit) {
  1738.     for (x = 0 ; x < SCSI_MAX_DISKS ; x++) {
  1739.         scsiDisk[x] = (DevSCSIDisk *)NIL;
  1740.     }
  1741.     scsiDiskInit = TRUE;
  1742.     }
  1743.  
  1744.     /*
  1745. d114 8
  1746. a121 7
  1747.     if (Sys_SetJump(&setJumpState) == SUCCESS) {
  1748.     x = regsPtr->dmaCount;
  1749.     regsPtr->dmaCount = (short)0xBABE;
  1750.     if (regsPtr->dmaCount != (short)0xBABE) {
  1751.         Sys_Printf("SCSI-%d: control register read-back problem\n",
  1752.                  scsiPtr->number);
  1753.         Sys_UnsetJump();
  1754. a124 1
  1755.     Sys_UnsetJump();
  1756. a131 1
  1757.     Sys_UnsetJump();
  1758. d139 4
  1759. a142 3
  1760.      * for reading and writing filesystem blocks.  A physical page is
  1761.      * obtained for the sense data and the label.  The general buffer gets
  1762.      * mapped just before a read or write.  It has to be twice as large as
  1763. d145 1
  1764. a145 4
  1765.     scsiPtr->senseBuffer =
  1766.         (DevSCSISense *)Vm_DevBufferAlloc(&devMultibusBuffer,
  1767.                            sizeof(DevSCSISense));
  1768.     Vm_GetDevicePage((int)scsiPtr->senseBuffer);
  1769. d147 1
  1770. a147 3
  1771.     scsiPtr->labelBuffer = Vm_DevBufferAlloc(&devMultibusBuffer,
  1772.                          BYTES_PER_SECTOR);
  1773.     Vm_GetDevicePage((int)scsiPtr->labelBuffer);
  1774. d149 1
  1775. a149 2
  1776.     scsiPtr->IOBuffer = Vm_DevBufferAlloc(&devMultibusBuffer,
  1777.                       2 * FS_BLOCK_SIZE);
  1778. a150 7
  1779.     /*
  1780.      * Initialize synchronization variables and set the controllers
  1781.      * state to alive and not busy.
  1782.      */
  1783.     scsiPtr->mutex = 0;
  1784.     scsiPtr->IOComplete.waiting = 0;
  1785.     scsiPtr->readyForIO.waiting = 0;
  1786. d204 1
  1787. d206 1
  1788. d235 1
  1789. a235 1
  1790.     DevSCSIRegs *regsPtr;
  1791. d267 1
  1792. a267 1
  1793.     status = DevSCSICommand(targetID, scsiPtr, 0, (Address)0, WAIT);
  1794. d295 25
  1795. d328 1
  1796. a328 1
  1797.                          scsiPtr->labelBuffer, WAIT);
  1798. d330 2
  1799. a331 2
  1800.     Sys_Printf("SCSI-%d: couldn't read the disk%d label\n",
  1801.                  scsiPtr->number, diskPtr->slaveID);
  1802. d353 1
  1803. d359 1
  1804. a359 1
  1805.  * DevSCSIIO --
  1806. d376 2
  1807. a377 2
  1808. DevSCSIIO(command, deviceUnit, buffer, firstSector, numSectorsPtr)
  1809.     int command;            /* SCSI_READ or SCSI_WRITE */
  1810. d380 1
  1811. a380 1
  1812.     char *buffer;            /* Target buffer */
  1813. a386 2
  1814.     int disk;        /* Disk number of disk that has the partition that
  1815.              * corresponds to the unit number */
  1816. d388 1
  1817. a388 1
  1818.     DevSCSIDisk *diskPtr;    /* State of the disk */
  1819. a392 1
  1820.     int lastSector;    /* Last sector of the partition */
  1821. a394 4
  1822.     disk = deviceUnit / DEV_NUM_DISK_PARTS;
  1823.     part = deviceUnit % DEV_NUM_DISK_PARTS;
  1824.     diskPtr = scsiDisk[disk];
  1825.  
  1826. d396 2
  1827. a397 3
  1828.      * Do bounds checking to keep the I/O within the partition.
  1829.      * sectorZero is the sector number of the first sector in the partition,
  1830.      * lastSector is the sector number of the last sector in the partition.
  1831. d399 2
  1832. a400 1
  1833.     sectorZero = diskPtr->map[part].firstCylinder *
  1834. a401 3
  1835.     lastSector = diskPtr->map[part].numCylinders *
  1836.          (diskPtr->numHeads * diskPtr->numSectors) +
  1837.          sectorZero - 1;
  1838. a402 14
  1839.  
  1840.     if ((firstSector + sectorZero) > lastSector) {
  1841.     /*
  1842.      * The offset is past the end of the partition.
  1843.      */
  1844.     *numSectorsPtr = 0;
  1845.     return(SUCCESS);
  1846.     } else if ((firstSector + sectorZero + totalSectors - 1) > lastSector) {
  1847.     /*
  1848.      * The transfer is at the end of the partition.  Reduce the
  1849.      * sector count so there is no overrun.
  1850.      */
  1851.     totalSectors = lastSector - (firstSector + sectorZero) + 1;
  1852.     }
  1853. d413 2
  1854. a414 1
  1855.     error = DevSCSISectorIO(command, diskPtr, sectorZero + firstSector,
  1856. d459 1
  1857. a460 4
  1858.     /*
  1859.      * Synchronize with the interrupt handling routine and with other
  1860.      * processes that are trying to initiate I/O with this controller.
  1861.      */
  1862. d462 1
  1863. a462 1
  1864.     MASTER_LOCK(scsiPtr->mutex);
  1865. a464 13
  1866.      * Here we are using a condition variable and the scheduler to
  1867.      * synchronize access to the controller.  An alternative would be
  1868.      * to have a command queue associated with the controller.  We can't
  1869.      * rely on the mutex variable because that is relinquished later
  1870.      * when the process using the controller waits for the I/O to complete.
  1871.      */
  1872.     while (scsiPtr->flags & SCSI_CNTRLR_BUSY) {
  1873.     Sync_MasterWait(&scsiPtr->readyForIO, &scsiPtr->mutex, FALSE);
  1874.     }
  1875.     scsiPtr->flags |= SCSI_CNTRLR_BUSY;
  1876.     scsiPtr->flags &= ~SCSI_IO_COMPLETE;
  1877.  
  1878.     /*
  1879. d468 1
  1880. a468 1
  1881.     buffer = Vm_DevBufferMap(*numSectorsPtr * BYTES_PER_SECTOR,
  1882. d470 1
  1883. a470 1
  1884.     DevSCSISetupCommand(command, diskPtr->slaveID, firstSector, *numSectorsPtr,
  1885. d473 4
  1886. a476 12
  1887.                  *numSectorsPtr * BYTES_PER_SECTOR,
  1888.                  buffer, INTERRUPT);
  1889.     /*
  1890.      * Wait for the command to complete.  The interrupt handler checks
  1891.      * for I/O errors, computes the residual, and notifies us.
  1892.      */
  1893.     if (error == SUCCESS) {
  1894.     while((scsiPtr->flags & SCSI_IO_COMPLETE) == 0) {
  1895.         Sync_MasterWait(&scsiPtr->IOComplete, &scsiPtr->mutex, FALSE);
  1896.     }
  1897.     }
  1898.     *numSectorsPtr -= (scsiPtr->residual / BYTES_PER_SECTOR);
  1899. a480 3
  1900.     scsiPtr->flags &= ~SCSI_CNTRLR_BUSY;
  1901.     Sync_MasterBroadcast(&scsiPtr->readyForIO);
  1902.     MASTER_UNLOCK(scsiPtr->mutex);
  1903. d504 5
  1904. a508 5
  1905.     char command;    /* One of six standard SCSI commands */
  1906.     int targetID;    /* Spefifies unit within the controller */
  1907.     int blockNumber;    /* The starting block number for the transfer */
  1908.     int numSectors;    /* Number of sectors to transfer */
  1909.     DevSCSIControlBlock *controlBlockPtr;
  1910. d526 3
  1911. a528 4
  1912.  *      been set up previously with DevSCSISetupCommand.  If the interrupt
  1913.  *      argument is WAIT (FALSE) then this waits around for the command to
  1914.  *      complete and checks the status results.  Otherwise Dev_SCSIIntr
  1915.  *      will be invoked later to check completion status.
  1916. d539 1
  1917. a539 1
  1918. DevSCSICommand(targetID, scsiPtr, size, addr, interrupt)
  1919. a547 7
  1920.     int interrupt;            /* WAIT or INTERRUPT.  If INTERRUPT
  1921.                      * then this procedure returns
  1922.                      * after initiating the command
  1923.                      * and the device interrupts
  1924.                      * later.  If WAIT this polls
  1925.                      * the SCSI interface register
  1926.                      * until the command completes. */
  1927. d572 1
  1928. d575 1
  1929. d588 1
  1930. a588 6
  1931.     if (interrupt == INTERRUPT) {
  1932.     regsPtr->control = SCSI_WORD_MODE|SCSI_DMA_ENABLE|
  1933.                 SCSI_INTERRUPT_ENABLE;
  1934.     } else {
  1935.     regsPtr->control = SCSI_WORD_MODE|SCSI_DMA_ENABLE;
  1936.     }
  1937. d601 1
  1938. d604 1
  1939. d613 1
  1940. d616 1
  1941. d622 8
  1942. a629 13
  1943.     if (interrupt == WAIT) {
  1944.     /*
  1945.      * A synchronous command.  Wait here for the command to complete.
  1946.      */
  1947.     error = DevSCSIWait(regsPtr, SCSI_INTERRUPT_REQUEST);
  1948.     if (error == SUCCESS) {
  1949.         error = DevSCSIStatus(scsiPtr);
  1950.         if (error != SUCCESS) {
  1951.         Sys_Printf("SCSI-%d: error getting status\n",
  1952.                      scsiPtr->number);
  1953.         }
  1954.     } else {
  1955.         Sys_Printf("SCSI-%d: couldn't wait for command to complete\n",
  1956. d633 2
  1957. a634 1
  1958.     error = SUCCESS;
  1959. d665 4
  1960. a668 4
  1961.     short message;
  1962.     char status;
  1963.     char *statusBytePtr;
  1964.     int numStatusBytes = 0;
  1965. d684 1
  1966. d687 1
  1967. d691 1
  1968. d697 1
  1969. d720 1
  1970. d722 1
  1971. d729 1
  1972. a729 1
  1973.                     (Address)scsiPtr->senseBuffer, WAIT);
  1974. d732 1
  1975. d736 1
  1976. d739 1
  1977. d744 1
  1978. d767 1
  1979. a767 1
  1980.     DevSCSIRegs *regsPtr;
  1981. a784 98
  1982. }
  1983.  
  1984. /*
  1985.  *----------------------------------------------------------------------
  1986.  *
  1987.  * Dev_SCSIIntr --
  1988.  *
  1989.  *    Handle interrupts from the SCSI controller.  This has to poll
  1990.  *    through the possible SCSI controllers to find the one generating
  1991.  *    the interrupt.  The usual action is to wake up whoever is waiting
  1992.  *    for I/O to complete.  This may also start up another transaction
  1993.  *    with the controller if there are things in its queue.
  1994.  *
  1995.  * Results:
  1996.  *    TRUE if an SCSI controller was responsible for the interrupt
  1997.  *    and this routine handled it.
  1998.  *
  1999.  * Side effects:
  2000.  *    Usually a process is notified that an I/O has completed.
  2001.  *
  2002.  *----------------------------------------------------------------------
  2003.  */
  2004. Boolean
  2005. Dev_SCSIIntr()
  2006. {
  2007.     ReturnStatus error;
  2008.     int index;
  2009.     register DevSCSIController *scsiPtr;
  2010.     register DevSCSIRegs *regsPtr;
  2011.  
  2012.     for (index = 0; index < SCSI_MAX_CONTROLLERS ; index++) {
  2013.     scsiPtr = scsi[index];
  2014.     if (scsiPtr == (DevSCSIController *)NIL) {
  2015.         continue;
  2016.     }
  2017.     regsPtr = scsiPtr->regsPtr;
  2018.     if (regsPtr->control & SCSI_INTERRUPT_REQUEST) {
  2019.         if (regsPtr->control & SCSI_BUS_ERROR) {
  2020.         if (regsPtr->dmaCount >= 0) {
  2021.             /*
  2022.              * A DMA overrun.  Unlikely with a disk but could
  2023.              * happen while reading a large tape block.  Consider
  2024.              * the I/O complete with no residual bytes
  2025.              * un-transferred.
  2026.             scsiPtr->residual = 0;
  2027.             scsiPtr->flags |= SCSI_IO_COMPLETE;
  2028.         } else {
  2029.             /*
  2030.              * A real Bus Error.  Complete the I/O but flag an error.
  2031.              * The residual is computed because the Bus Error could
  2032.              * have occurred after a number of sectors.
  2033.              */
  2034.             scsiPtr->residual = -regsPtr->dmaCount -1;
  2035.             scsiPtr->flags |= (SCSI_IO_ERROR | SCSI_IO_COMPLETE);
  2036.         }
  2037.         /*
  2038.          * The board needs to be reset to clear the Bus Error
  2039.          * condition so no status bytes are grabbed.
  2040.          */
  2041.         DevSCSIReset(scsiPtr->regsPtr);
  2042.         Sync_MasterBroadcast(&scsiPtr->IOComplete);
  2043.         return(TRUE);
  2044.         } else {
  2045.         /*
  2046.          * Normal command completion.  Compute the residual,
  2047.          * the number of bytes not transferred, check for
  2048.          * odd transfer sizes, and finally get the completion
  2049.          * status from the device.
  2050.          */
  2051.         scsiPtr->residual = -regsPtr->dmaCount -1;
  2052.         if (regsPtr->control & SCSI_ODD_LENGTH) {
  2053.             /*
  2054.              * On a read the last odd byte is left in the data
  2055.              * register.  On both reads and writes the number
  2056.              * of bytes transferred as determined from dmaCount
  2057.              * is off by one.  See Page 8 of Sun's SCSI
  2058.              * Programmers' Manual.
  2059.              */
  2060.             if (scsiPtr->controlBlock.command == SCSI_READ) {
  2061.             *(char *)(MULTIBUS_BASE + regsPtr->dmaAddress) =
  2062.                 regsPtr->data;
  2063.             scsiPtr->residual--;
  2064.             } else {
  2065.             scsiPtr->residual++;
  2066.             }
  2067.         }
  2068.         error = DevSCSIStatus(scsiPtr);
  2069.         if (error != SUCCESS) {
  2070.             Sys_Printf("SCSI-%d: error getting status\n",
  2071.                      scsiPtr->number);
  2072.         }
  2073.         scsiPtr->flags |= SCSI_IO_COMPLETE;
  2074.         Sync_MasterBroadcast(&scsiPtr->IOComplete);
  2075.         return(TRUE);
  2076.         }
  2077.     }
  2078.     }
  2079.     return(FALSE);
  2080. @
  2081.